﻿using System;
using System.Collections.Generic;
using System.Linq;
using CLM.Gestao.Interfaces;
using CLM.Gestao.Administrador.DAL;
using CLM.Gestao.Importacao;
using System.Data;

namespace CLM.Gestao.Administrador.BLL
{
    public class ProdutoFamilia : ProdutoFamiliaBLO<TB_PRODUTO_FAMILIA>
    {
        #region Propriedades

        public int IdProdutoFamilia { get; set; }
        public string NomeProdutoFamilia { get; set; }
        public bool IndicaRecebeTradeAllowances { get; set; }
        public bool IndicaAtivo { get; set; }

        #endregion Propriedades

        #region Conversões

        private List<TB_PRODUTO_FAMILIA> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_PRODUTO_FAMILIA> List = (from l in pLista
                                             select new TB_PRODUTO_FAMILIA
                                             {
                                                 ID_PRODUTO_FAMILIA = l.IdProdutoFamilia,
                                                 NOME_PRODUTO_FAMILIA = l.NomeProdutoFamilia.Trim(),
                                                 INDICA_RECEBE_TRADE_ALLOWANCES = l.IndicaRecebeTradeAllowances,
                                                 INDICA_ATIVO = l.IndicaAtivo,
                                                 ORDEM_EXIBICAO = l.OrdemExibicao
                                             }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_PRODUTO_FAMILIA> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    IdProdutoFamilia = l.ID_PRODUTO_FAMILIA,
                                    NomeProdutoFamilia = l.NOME_PRODUTO_FAMILIA.Trim(),
                                    IndicaRecebeTradeAllowances = l.INDICA_RECEBE_TRADE_ALLOWANCES,
                                    IndicaAtivo = l.INDICA_ATIVO,
                                    OrdemExibicao = l.ORDEM_EXIBICAO
                                }).ToList();
            return List;
        }

        #endregion Conversões

        #region CRUD
        /// <summary>
        /// Adiciona
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Deleta
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Atualiza
        /// </summary>
        /// <param name="pLista">pLista</param>
        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Efetua a pesquisa na tabela, filtrando as solicitações do usuário
        /// </summary>
        /// <param name="pPesquisa">pPesquisa</param>
        /// <returns>Lista</returns>
        private IQueryable<TB_PRODUTO_FAMILIA> Get(Lista pPesquisa)
        {
            IQueryable<TB_PRODUTO_FAMILIA> Consulta;

            Consulta = from p in GetAll()
                       orderby p.ORDEM_EXIBICAO
                       select p;
            if (pPesquisa != null)
            {
                if (pPesquisa.IdProdutoFamilia > 0)
                    Consulta = from p in Consulta where p.ID_PRODUTO_FAMILIA == pPesquisa.IdProdutoFamilia select p;
            }
            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            var ListaProdutoFamilia = ConvertToContext(Get(pPesquisa));
            return ListaProdutoFamilia;
        }

        public List<Itens> GetItens()
        {
            return GetItens(new Lista());
        }

        public List<Itens> GetItens(Lista pPesquisa)
        {
            List<Itens> ListaProdutoFamilia = (from p in Get(pPesquisa)
                                        select new Itens()
                                        {
                                            IdProdutoFamilia = p.ID_PRODUTO_FAMILIA,
                                            NomeProdutoFamilia = p.NOME_PRODUTO_FAMILIA
                                        }).ToList();
            return ListaProdutoFamilia;
        }

        #endregion Retorna Listas e Itens

        #region Processos

        #region Importar Ordem

        private DataSet dsProdutos;
        private Importacao.Excel ExcelConnection;

        public void ImportaOrdemFamiliaProdutosGlobais(string pFileName)
        {
            ExcelConnection = new Importacao.Excel();
            dsProdutos = null;

            ValidaLayoutImportacaoOrdem(pFileName);
            ValidaDadosImportacaoOrdem();

            AtualizaOrdemProduto();
        }

        private void ValidaLayoutImportacaoOrdem(string pFileName)
        {
            // Acessa o documento Excel e efetua a consulta na planilha "Dados"
            try { dsProdutos = ExcelConnection.ExecuteRecordset(pFileName, "SELECT * FROM [Dados$]"); }
            catch { throw new Exception("A planilha não possui a aba \"Dados\"."); }

            if (dsProdutos != null && dsProdutos.Tables != null && dsProdutos.Tables.Count > 0 && dsProdutos.Tables[0].Rows.Count > 0)
            {
                try { var aux = dsProdutos.Tables[0].Rows[0].Field<object>("Familia Hyperion"); }
                catch { throw new Exception("A coluna (\"Familia Hyperion\") não foi encontrada no arquivo."); }
            }
        }

        private void ValidaDadosImportacaoOrdem()
        {
        }

        private void AtualizaOrdemProduto()
        {
            ProdutoFamilia Familia = new ProdutoFamilia();
            OnImportData(this, new ImportDataEventArgs("Importando ordem de Família de Produtos Globais..."));

            // Colunas A, D
            int Ord = 0;
            var ProdutosExcel = (from p in dsProdutos.Tables[0].AsEnumerable()
                                 select new ProdutoFamilia.Lista
                                 {
                                     NomeProdutoFamilia = p.Field<string>("Familia Hyperion"),
                                     OrdemExibicao = Ord++
                                 }).ToList();

            var ProdutosSQL = (from p in Familia.GetLista()
                               select new ProdutoFamilia.Lista
                               {
                                   NomeProdutoFamilia = p.NomeProdutoFamilia,
                                   IdProdutoFamilia = p.IdProdutoFamilia
                               }).ToList();

            var Alterados = (from p in ProdutosExcel
                             join db in ProdutosSQL
                             on p.NomeProdutoFamilia equals db.NomeProdutoFamilia
                             select new ProdutoFamilia.Lista
                             {
                                 IdProdutoFamilia = db.IdProdutoFamilia,
                                 NomeProdutoFamilia = p.NomeProdutoFamilia,
                                 OrdemExibicao = p.OrdemExibicao
                             }).ToList();
            int i = 0;
            if (Alterados != null && Alterados.Count() > 0)
            {
                foreach (var item in Alterados)
                {
                    Familia.Update(new TB_PRODUTO_FAMILIA()
                    {
                        ID_PRODUTO_FAMILIA = item.IdProdutoFamilia,
                        NOME_PRODUTO_FAMILIA = item.NomeProdutoFamilia,
                        ORDEM_EXIBICAO = item.OrdemExibicao,
                        INDICA_ATIVO = true
                    });
                    i++;
                    OnImportData(this, new ImportDataEventArgs("Atualizando ordem de Família de Produtos Globais...", i, Alterados.Count()));
                }
            }
        }

        #endregion
        
        #endregion

        #region Consultas

       
        #endregion Consultas

        #region Classes

        /// <summary>
        /// Preenche o combobox
        /// </summary>
        public class Itens
        {
            public int IdProdutoFamilia { get; set; }
            public string NomeProdutoFamilia { get; set; }
        }

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public int IdProdutoFamilia { get; set; }
            public string NomeProdutoFamilia { get; set; }
            public bool IndicaRecebeTradeAllowances { get; set; }
            public bool IndicaAtivo { get; set; }
            public int OrdemExibicao { get; set; }
        }

        #endregion Classes

        public event ImportDataEventHandler OnImportData;
    }

    public class ProdutoFamiliaBLO<T> : IBLO<T> where T : TB_PRODUTO_FAMILIA
    {
        /// <summary>
        /// ProdutoFamiliaDAO
        /// </summary>
        private ProdutoFamiliaDAO<T> _base = new ProdutoFamiliaDAO<T>();

        /// <summary>
        /// Adiciona uma entidade no sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Salva uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Save(T pEntity)
        {
            Validate(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Deleta uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        public void Delete(T pEntity)
        {
            _base.Delete(pEntity);
            _base.Save(pEntity);
        }

        /// <summary>
        /// Atualiza uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public T Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            return _base.Save(pEntity);
        }

        /// <summary>
        /// Recupera uma entidade do sistema
        /// </summary>
        /// <returns>Lista</returns>
        public IQueryable<T> GetAll()
        {
            return _base.GetAll();
        }

        /// <summary>
        /// Valida a consistência da Entidade antes de 'comitar' a transação
        /// </summary>
        /// <param name="pEntity">Entidade</param>
        public void Validate(T pEntity)
        {

        }
    }
}